#! /usr/bin/env python
# -*- coding: utf-8 -*-
import asyncio
import json
import logging

import requests

import itchat
from src.Queue import queue
from src.help import check_at
from src.result import callback_cycle
from src.tasks import Action, Tasks
from src.tasks import tasks_cycle

KEY = '1add8034326748b7a45d8db09186b7d4'
tasks_dict = {}


def get_response(msg):
    # 这里我们就像在“3. 实现最简单的与图灵机器人的交互”中做的一样
    # 构造了要发送给服务器的数据
    apiUrl = 'http://www.tuling123.com/openapi/api/v2'
    data = {
        "reqType": 0,
        "perception": {
            "inputText": {
                "text": msg
            }
        },
        "userInfo": {
            "apiKey": KEY,
            "userId": "itchat"
        }
    }
    try:
        data = json.dumps(data)
        r = requests.post(apiUrl, data=data).json()
        """
        {'emotion':{'robotEmotion': {'a': 0, 'd': 0, 'emotionId': 0, 'p': 0}, 
         'userEmotion': {'a': 0, 'd': 0, 'emotionId': 0, 'p': 0}}, 
         'intent': {'actionName': '', 'code': 10004, 'intentName': ''}, 
         'results': [{'groupType': 0, 'resultType': 'text', 'values': {'text': '说说你，不说他啦，嘿嘿。'}}]
         }
        """
        rsp = r.get('results')
        # 字典的get方法在字典没有'text'值的时候会返回None而不会抛出异常
        str_ = ''
        for items in rsp:
            str_ += items.get('values').get('text')
        return str_
    # 为了防止服务器没有正常响应导致程序异常退出，这里用try-except捕获了异常
    # 如果服务器没能正常交互（返回非json或无法连接），那么就会进入下面的return
    except:
        # 将会返回一个None
        return


@itchat.msg_register(itchat.content.TEXT, isGroupChat=True)
def tuling_reply(msg):
    # group = itchat.get_chatrooms(update=True)
    flag, text = check_at(msg['Text'])
    if flag:
        # 此时需要 格式化 text 然后增加到 任务中，
        # 需要记录的是 哪个群 msg['FromUserName']
        # msg['ActualUserName'] # 群信息实际发送人
        # msg['CreateTime'] # 创建时间
        logging.info(f"{msg['FromUserName']}  收到消息:{text}")
        if "提醒" in text:
            msg_ = "小白为你服务！\n@小白 每天 几点几分 提醒 msg\n或者\n@小白 9月7号 10点10分 提醒 msg"
            msg.user.send(msg_)
            put_date_queue(data=text, obj=msg, flag=0)
        elif "列表" in text:
            flag = True
            if len(tasks_dict) == 0:
                flag = False
            for key, items in tasks_dict.items():
                print(msg['FromUserName'])
                print(tasks_dict)
                if key == msg['FromUserName']:
                    if len(items) == 0:
                        flag = False
                    else:
                        for k, v in items.items():
                            msg.user.send("任务名称:{}  任务内容:{}".format(k, v))
                            logging.info("任务名称:{}  任务内容:{}".format(k, v))
            if flag == False:
                msg.user.send("= = Orz 列表为空")
        elif "删除" in text:
            put_date_queue(data=text, obj=msg, flag=1)
        else:
            try:
                reply = get_response(text)
            except Exception as e:
                reply = "你说啥呢？"
            msg.user.send(f"@{msg['ActualNickName']} {reply}")
    # print(msg['FromUserName']) # 接受的群 名称 @@e9db2f2006ac098128a94b089b09662d2ceeae946799776d8764364f3250c2c5
    # print(msg['CreateTime']) # 创建时间
    # print(msg['Text']) # 内容 @抱着吉他吃西瓜\u2005今天不加班吧？
    # print(msg['ActualUserName']) # 群信息实际发送人
    # msg.user.send("") # 可以保存msg对象

def lc():
    logging.info('登录成功')
def ec():
    logging.info('成功退出')

async def weixin(future):
    # 启动 微信客户端
    itchat.auto_login(hotReload=True,enableCmdQR=2,loginCallback=lc, exitCallback=ec)
    # itchat.auto_login(hotReload=True,loginCallback=lc, exitCallback=ec)
    itchat.run(blockThread=False)  # 另外一个线程


def put_date_queue(data, obj, flag):
    from src.tasks import Tasks, Action
    from src.Queue import queue
    timed_obj = None
    if flag == 0:
        try:
            timed_obj = Tasks(msg=data, obj=obj)
            if not tasks_dict.get(obj['FromUserName']):
                tasks_dict[obj['FromUserName']] = {}
            tasks_dict[obj['FromUserName']][
                timed_obj.task_name] = timed_obj.msg
            obj.user.send("已经收到提醒，将在 {}小时{}分钟 后提醒".format(timed_obj.del_hour,
                                                          timed_obj.del_min))
        except Exception as e:
            msg_ = "你的格式有问题   记得空格哦"
            obj.user.send(msg_)
    if flag == 1:
        try:
            timed_obj = Action(msg=data)
            obj.user.send("已经删除任务为：{} {}".format(timed_obj.task_name,
                                                 tasks_dict[
                                                     obj['FromUserName']][
                                                     timed_obj.task_name]))
            del tasks_dict[obj['FromUserName']][timed_obj.task_name]
        except Exception as e:
            msg_ = "你的格式有问题\n@小白 列表 \n@小白 删除 任务名称"
            obj.user.send(msg_)
    msg = 'Tasks is ok >>>>'
    logging.info(msg)
    queue.put_nowait(timed_obj)
    msg = 'Now queue size ===== {}'.format(queue.qsize())
    logging.info(msg)


def start_loop(loop):
    asyncio.set_event_loop(loop)
    future = asyncio.Future()
    asyncio.ensure_future(weixin(future), loop=loop)
    future.add_done_callback(callback_cycle)
    loop.run_forever()


async def slow_operation(loop):
    task_rule_action = []
    while True:
        if queue.qsize() == 0:
            await  asyncio.sleep(1)
        else:
            flag = False
            try:
                timed_obj = queue.get_nowait()
                msg = 'Get from queue >>>>{}'.format(timed_obj)
                logging.info(msg)
            except Exception as e:
                timed_obj = None
            if isinstance(timed_obj, Action):
                task_rule_action.append(timed_obj)
            if timed_obj is not None and isinstance(timed_obj, Tasks):
                for items in task_rule_action:
                    if items.task_name == timed_obj.task_name:
                        # todo action 更新，或者删除。
                        if items.action == 'delete':
                            flag = True
                        elif items.action == 'update':
                            timed_obj.update(items.task_data)
                        else:
                            pass
                        task_rule_action.remove(items)
                if flag == False:
                    try:
                        future_ = asyncio.Future()
                        asyncio.run_coroutine_threadsafe(
                            tasks_cycle(future_, timed_obj), loop)
                        future_.add_done_callback(callback_cycle)
                        logging.info('tasks_cycle callback   have done ')
                    except Exception as e:
                        logging.info(e)
